#!/usr/bin/python
# -*- encoding: utf-8 -*-

"""
@File:      tc_libtevent_libtevent_func_003.py
@Time:      2024/04/23 14:51:50
@Author:    zhixin
@Version:   1.0
@Contact:   zx01468051@alibaba-inc.com
@License:   Mulan PSL v2
@Modify:    zhixin
"""

from common.basetest import LocalTest
import re

class Test(LocalTest):
    """
    See tc_libtevent_libtevent_func_003.yaml for details

    :avocado: tags=P2,noarch,local,fix
    """
    PARAM_DIC = {"pkg_name": "libtevent libtevent-devel libtalloc-devel gcc"}
    def setUp(self):
        super().setUp(self.PARAM_DIC)
        cmdline = """cat > tevent_test3.c <<EOF
#include <stdio.h>
#include <unistd.h>
#include <tevent.h>
#include <string.h>
#include <stdbool.h>

struct tevent_fd_test {
    struct tevent_context *ev_ctx;
    bool done;
    int fd; // 加入文件描述符字段
};

// 文件描述符事件回调函数
static void fd_event_handler(struct tevent_context *ev,
                             struct tevent_fd *fde,
                             uint16_t flags,
                             void *private_data)
{
    struct tevent_fd_test *test_data = (struct tevent_fd_test *)private_data;

    if (flags & TEVENT_FD_READ) {
        printf("文件描述符准备好读取！\\n");

        // 读取管道中的数据
        char buf[1024];
        memset(buf, 0, sizeof(buf)); // 确保缓冲区被清空
        int bytes_read = read(test_data->fd, buf, sizeof(buf) - 1);
        if (bytes_read > 0) {
            printf("读取内容：%s\\n", buf);
        } else {
            printf("读取错误或管道关闭\\n");
        }
        // 注销文件描述符事件并关闭文件描述符
        tevent_fd_set_flags(fde, 0);
        close(test_data->fd);

        // 设置完成标志以结束事件循环
        test_data->done = true;
    }
}

int main(void)
{
    // 创建管道
    int fds[2];
    if (pipe(fds) == -1) {
        perror("创建管道失败");
        return -1;
    }

    struct tevent_fd_test test_data = {
        .done = false,
        .fd = fds[0] // 初始化文件描述符
    };

    // 创建 tevent 上下文
    test_data.ev_ctx = tevent_context_init(NULL);
    if (test_data.ev_ctx == NULL) {
        fprintf(stderr, "无法初始化 tevent 上下文\\n");
        close(fds[0]);
        close(fds[1]);
        return -1;
    }

    // 为读端文件描述符添加事件监听
    struct tevent_fd *read_fde = tevent_add_fd(test_data.ev_ctx, NULL, fds[0], 
                TEVENT_FD_READ, fd_event_handler, &test_data);
    if (read_fde == NULL) {
        fprintf(stderr, "无法为文件描述符添加事件监听\\n");
        close(fds[0]);
        close(fds[1]);
        TALLOC_FREE(test_data.ev_ctx);
        return -1;
    }

    // 向管道写入数据，并关闭写端
    const char *message = "Hello, tevent!";
    if (write(fds[1], message, strlen(message) + 1) < 0) {
        perror("写入管道失败");
    }
    close(fds[1]);

    // 执行事件循环，等待事件发生或直到 done 标志位被设置
    printf("开始事件循环...\\n");
    while (!test_data.done) {
        tevent_loop_once(test_data.ev_ctx);
    }

    // 事件循环结束后清理资源
    TALLOC_FREE(test_data.ev_ctx);

    return 0;
}
EOF"""

        self.cmd(cmdline)
    
    def test(self):
        self.cmd('gcc -o tevent_test3 tevent_test3.c -ltevent -ltalloc')
        code, tevent_result = self.cmd("./tevent_test3")
        self.assertIn('读取内容：Hello, tevent!', tevent_result)

    def tearDown(self):
        super().tearDown(self.PARAM_DIC)
        self.cmd('rm -rf tevent_test3.c tevent_test3')
